package com;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;

/**
 * 
 * @author yindong
 * @time 2018-01-15
 * @version 1.0.0
 * 报表工具类
 */
public class ReportUtils {
	/**
	 * 报表生成方法 
	 * @param oldFilePath 报表模板路径	
	 * @param newFilePath 生成报表路径	
	 * @param newFileName 生成报表名称
	 * @param map 数据源  包含 第几个sheet页 以及所对应List<Map<String,Object>>数据源
	 * @param sheetMap  报表模板的sheet页
	 */
	public static boolean exportExcel(String oldFilePath,String newFilePath,String newFileName, Map<String,List<Map<String,Object>>> map,Map<String,Integer> sheetMap) {
		File newFile = createNewFile(oldFilePath,newFilePath,newFileName);
		InputStream is = null;
		HSSFWorkbook workbook = null;
		HSSFSheet sheet = null;
		try {
			is = new FileInputStream(newFile);
			workbook = new HSSFWorkbook(is);
			//声明变量接收数据源
			List<Map<String,Object>> list;
			//遍历数据源
			for(Map.Entry<String, List<Map<String, Object>>> mapValue:map.entrySet()){
				//根据sheet名获取对应的位置
				sheet = workbook.getSheetAt(sheetMap.get(mapValue.getKey()));
				if(sheet==null){
					return false;
				}
				//获取每个sheet页对应的数据源
				list = mapValue.getValue();
				//生成数据
				insertReportValue(list,is,workbook,sheet);
			}
			//将数据写到模板中
			FileOutputStream fos = new FileOutputStream(newFile);
			workbook.write(fos);
			fos.flush();
			//关闭流
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	/**
	 * 报表数据生成
	 * @param newFile 生成报表文件
	 * @param map  数据源
	 * @param is 输入流
	 * @param workbook excel类
	 * @param sheet excel模板sheet页
	 */
	private static void insertReportValue(List<Map<String,Object>> list,InputStream is,HSSFWorkbook workbook ,HSSFSheet sheet){
		try {
			//循环外声明变量
			Matcher y;
			Matcher mal;
			HSSFCell cell;
			//遍历集合 
			for(Map.Entry<String, Object> m:list.get(0).entrySet()){
				//利用正则表达式获取数据源中map->key值中的行数
				y = Pattern.compile("[^0-9]").matcher(m.getKey()); 
				//设置第几行开始  解析获取数字  第几行  行数从0开始
				HSSFRow row = sheet.getRow(Integer.valueOf(y.replaceAll("").trim().toString())-1);
				//判断当前状态是不是空，判断最大边框
				if (row == null) {
					row = sheet.createRow(Integer.valueOf(y.replaceAll("").trim().toString()));
				}
				//利用正则表达式获取数据源中map->key值中的列名  如：ABC..
		        mal=Pattern.compile("[A-Z]+").matcher(m.getKey());  
		        mal.find();
		        //poi自带方法根据列名转换成数字 该方法返回值从0开始
				cell = row.getCell(CellReference.convertColStringToIndex(mal.group()));
				if (cell == null) {
					//设置第几列开始
					cell = row.createCell(CellReference.convertColStringToIndex(mal.group()));
				}
		    	//设置存入内容为字符串  
		        cell.setCellType(HSSFCell.CELL_TYPE_STRING);  
		        //向单元格中放入值 
		        if(Double.parseDouble(m.getValue().toString())!=0){
		        	cell.setCellValue(Double.parseDouble(m.getValue().toString()));
		        }
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != is) {
					is.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 读取报表模板
	 * @param oldFilePath 报表模板路径
	 * @param newFilePath 报表生成路径
	 * @param newFileName 生成报表名称
	 * @return File 
	 */
	private static File createNewFile(String oldFilePath,String newFilePath,String newFileName) {
		File file = new File(oldFilePath);
		File dir = new File(newFilePath);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		File newFile = new File(newFilePath,newFileName);
		try {
			newFile.createNewFile();
			fileChannelCopy(file, newFile);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return newFile;
	}
	/**
	 * 将文件读到io流中
	 * @param oldFile 报表模板路径
	 * @param newFile 报表生成路径
	 * @void
	 */
	private static void fileChannelCopy(File oldFile, File newFile) {
		try {
			InputStream in = null;
			OutputStream out = null;
			try {
				in = new BufferedInputStream(new FileInputStream(oldFile), 1024);
				out = new BufferedOutputStream(new FileOutputStream(newFile), 1024);
				byte[] buffer = new byte[1024];
				int len;
				while ((len = in.read(buffer)) != -1) {
					out.write(buffer, 0, len);
				}
			} finally {
				if (null != in) {
					in.close();
				}
				if (null != out) {
					out.close();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
